/***************************************************************************
*  Trayicon.cpp
*
*  July 2007
*  Copyright  2007  RuijinZheng,China
*  Email mebetop@126.com
****************************************************************************/

/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#include <QMessageBox>
#include <QStringList>
#include <QString>
#include <QFile>
#include <QTime>
#include <QIODevice>
#include <QTextStream>
#include <QAction>
#include <QIcon>
#include <QMenu>
#include <QApplication>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "Configurebase.h"
#include "Trayicon.h"

Trayicon::Trayicon(const QIcon & icon, QObject * parent):QSystemTrayIcon(icon,parent){
     setToolTip(tr("Netflea : a proxy client program of delicacy.\nAny suggestions,please contact :\nEmail :mebetop@126.com \nOICQ:191542544"));
     readbuf=0;
     readbuf = new char[BUFFERSIZE];
     umask(0);
     mknod(FIFO_FILE,S_IFIFO|0666,0);
     ///////////////////
     QMenu *context = new QMenu();
     iconQuit = new QIcon(":/icons/exit.png");
     quitAct = context->addAction(*iconQuit,tr("Exit"));
     quitAct->setCheckable(true);
     setContextMenu(context);
     ////////////////////
     connect(this, SIGNAL(recvFinish(QStringList)), this, SLOT(showMsg(QStringList)));
     connect(this, SIGNAL(subthreadError(QString)), this, SLOT(showsubthreadMsg(QString)));
     ////////////////////
     connect(quitAct, SIGNAL(toggled(bool)), this, SLOT(quitNetflea()));
     ///////////////
     recvThread=0;
     this->starListenThread();
}
Trayicon::~Trayicon(){
     if(recvThread != 0)
         pthread_cancel(recvThread);
     if(readbuf!=0)
          delete [] readbuf;
}
void Trayicon::showMsg(QStringList msglist){
     showMessage(tr("Program name: %1")
          .arg(msglist[0]),
          tr("Discription: %1\nError message: %2")
          .arg(msglist[1])
          .arg(msglist[2]));
}
void Trayicon::showsubthreadMsg(QString msg){
     QMessageBox::critical(0, tr("Error"),tr("%1")
                  .arg(msg));
}
void Trayicon::recvMessage(Trayicon *sysicon){
     pthread_detach(pthread_self());
     int ret,fifovalue; 
     bool savelog;
     ConfigureBase *tmp=new ConfigureBase();
     tmp->readSettings();
     if(tmp->getSaveLogOrNot()==true){
    	 savelog=true;
     }
     else{
    	 savelog=false;
     }
     delete tmp;
     if((fifovalue = open(FIFO_FILE,O_RDONLY | O_NONBLOCK))<=0){
    	 emit sysicon->subthreadError(tr("Error occured while opening FIFO file:\n %1")
    			 .arg(FIFO_FILE));
      }
     else{
    	      if(savelog==true){
               QString logpath=QString(getenv("HOME"))+QString("/.netflea/log");
               QFile log(logpath); 
               if(!log.open(QIODevice::ReadWrite|QIODevice::Append)){
            	        emit sysicon->subthreadError(tr("Error occured while opening file:\n%1")
            	        		.arg(logpath));
                  }
               else{
                      QTextStream in(&log);
                      do{
                          sysicon->timeout.tv_sec=1;
                          sysicon->timeout.tv_usec=0;
                          FD_ZERO(&(sysicon->readfd));
                          FD_SET(fifovalue,&(sysicon->readfd));
                    	  ret=select(fifovalue+1,&(sysicon->readfd),NULL,NULL,&(sysicon->timeout));
                    	  if(FD_ISSET(fifovalue,&(sysicon->readfd))){
                    		  memset(sysicon->readbuf,0,BUFFERSIZE);
                    		  if(read(fifovalue,sysicon->readbuf,BUFFERSIZE)>0){
                                QString message(sysicon->readbuf);
                                QStringList msglist = message.split("@",
                                QString::SkipEmptyParts);
                                in<<tr("Time :%1\nProgram name:%2\nDescription:%3\nError message:%4\n\n") 
                                     .arg(QTime::currentTime().toString())
                                     .arg(msglist[0])
                                     .arg(msglist[1])
                                     .arg(msglist[2]);
                                in.flush();
                                emit sysicon->recvFinish(msglist);
                    		     }
                    	  	  }
                    	  usleep(1000);
                      }while(1);
                  }
               log.close();
            }else{
                do{
                    sysicon->timeout.tv_sec=1;
                    sysicon->timeout.tv_usec=0;
                    FD_ZERO(&(sysicon->readfd));
                    FD_SET(fifovalue,&(sysicon->readfd));
              	    ret=select(fifovalue+1,&(sysicon->readfd),NULL,NULL,&(sysicon->timeout));
              	    if(FD_ISSET(fifovalue,&(sysicon->readfd))){
              		     memset(sysicon->readbuf,0,BUFFERSIZE);
              		     if(read(fifovalue,sysicon->readbuf,BUFFERSIZE)>0){
                           QString message(sysicon->readbuf);
                           QStringList msglist = message.split("@",
                           QString::SkipEmptyParts);
                          emit sysicon->recvFinish(msglist);
              		         }
              	  	    }
              	  usleep(1000);
                }while(1);
            }
     }
}
int Trayicon::starListenThread(){
     int ret;
     ret = pthread_create(&recvThread, NULL, (void*(*)(void*))(Trayicon::recvMessage), (void*)this);
     if(ret){
          QMessageBox::critical(0, tr("Error"),tr("error occured while creating sub thread,netflea exiting..."));
     }
     return ret;
}
void Trayicon::quitNetflea()
{
     qApp->quit();
}